﻿using System;
using System.DirectoryServices.Protocols;
using ActiveDirectoryUtilities.DirectoryServiceAccess;

namespace ActiveDirectoryUtilities.CommonLibrary
{
	/// <summary>
	/// Allows for locating the identity referenced by a Guid in AD.
	/// </summary>
	class GuidFinder
	{
		private GuidFinder()
		{
		}

		static public string TranslateExtendedRightGuidToFriendlyName(Guid rightsGuid)
		{
			Guid dummy = Guid.Empty;
			return TranslateExtendedRightGuidToFriendlyName(rightsGuid, out dummy);
		}

		static public string TranslateExtendedRightGuidToFriendlyName(Guid rightsGuid, out Guid objectGuid)
		{
			if (rightsGuid == Guid.Empty)
			{
				objectGuid = Guid.Empty;
				return string.Empty;
			}
			else
			{
				RootDse dse = new RootDse();

				WLdapSearchRequest wlsr = new WLdapSearchRequest(
					string.Empty
					, (int)LDAP_PORTS.LDAP
					, dse.ConfigurationNamingContext
					, "(&(objectCategory=controlAccessRight)(rightsGuid=" + rightsGuid.ToString("D") + "))"
					, SearchScope.Subtree
					, new string[] {"displayName", "objectGUID"}
					);

				SearchResultEntry sre = wlsr.FindOne();

				if (sre != null)
				{
					objectGuid = GlobalMethods.ConvertDirectoryAttributeByteArrayToGuid(sre.Attributes["objectGUID"]);
					if (sre.Attributes.Contains("displayName"))
					{
						return sre.Attributes["displayName"][0].ToString();
					}
				}
			}

			//return empty string if the guid isn't empty or found
			objectGuid = Guid.Empty;
			return string.Empty;
		}

		static public string TranslateObjectTypeSchemaIDGuidToFriendlyName(Guid schemaIDGuid)
		{
			Guid dummy = Guid.Empty;
			return TranslateObjectTypeSchemaIDGuidToFriendlyName(schemaIDGuid, out dummy);
		}

		static public string TranslateObjectTypeSchemaIDGuidToFriendlyName(Guid schemaIDGuid, out Guid objectGuid)
		{
			if (schemaIDGuid == Guid.Empty)
			{
				objectGuid = Guid.Empty;
				return "All";
			}
			else
			{
				RootDse dse = new RootDse();

				WLdapSearchRequest wlsr = new WLdapSearchRequest(
					string.Empty
					, (int)LDAP_PORTS.LDAP
					, dse.SchemaNamingContext
					, "(schemaIDGuid=" + GlobalMethods.ConvertGuidToLdapSearchString(schemaIDGuid) + ")"
					, SearchScope.Subtree
					);
				wlsr.Attributes.Add("lDAPDisplayName");
				wlsr.Attributes.Add("objectGUID");
				SearchResultEntry sre = wlsr.FindOne();

				if (sre != null)
				{
					objectGuid = GlobalMethods.ConvertDirectoryAttributeByteArrayToGuid(sre.Attributes["objectGUID"]);
					if (sre.Attributes.Contains("lDAPDisplayName"))
					{
						return sre.Attributes["lDAPDisplayName"][0].ToString();
					}
				}
			}

			//return empty string if the guid isn't empty or found
			objectGuid = Guid.Empty;
			return string.Empty;
		}

		static public string TranslateObjectGuidToDistingushedName(Guid objectGuid)
		{
			byte[] g = objectGuid.ToByteArray();
			string queryGuid = string.Empty;
			foreach (byte b in g)
			{
				queryGuid += @"\" + b.ToString("x2");
			}

			RootDse dse = new RootDse(string.Empty, (int)LDAP_PORTS.Global_Catalog);

			WLdapSearchRequest wlsr = new WLdapSearchRequest(
				dse.DnsHostName
				, (int)LDAP_PORTS.Global_Catalog
				, string.Empty
				, "(objectGuid=" + queryGuid + ")"
				, SearchScope.Subtree);

			SearchResultEntry sre = wlsr.FindOne();

			if (sre != null)
			{
				return sre.DistinguishedName;
			}

			return string.Empty;
		}

		static public string TranslateCNOfGuidToDistinguishedName(Guid cnGuid)
		{
			Guid dummy = Guid.Empty;
			return TranslateCNOfGuidToDistinguishedName(cnGuid, out dummy);
		}

		static public string TranslateCNOfGuidToDistinguishedName(Guid cnGuid, out Guid objectGuid)
		{
			if (cnGuid == Guid.Empty)
			{
				objectGuid = Guid.Empty;
				return "All";
			}
			else
			{
				RootDse dse = new RootDse();

				WLdapSearchRequest wlsr = new WLdapSearchRequest(
					string.Empty
					, (int)LDAP_PORTS.Global_Catalog
					, string.Empty
					, "(cn=" + cnGuid.ToString("B") + ")"
					, SearchScope.Subtree
					);
				wlsr.Attributes.Add("objectGUID");
				SearchResultEntry sre = wlsr.FindOne();

				if (sre != null)
				{
					objectGuid = GlobalMethods.ConvertDirectoryAttributeByteArrayToGuid(sre.Attributes["objectGUID"]);
					return sre.DistinguishedName;
				}
			}

			//return empty string if the guid isn't empty or found
			objectGuid = Guid.Empty;
			return string.Empty;
		}
	}
}
